package com.tangruojie.stream;

import com.tangruojie.entity.Author;
import com.tangruojie.entity.Book;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * 中间操作之 flatMap 扁平化
 */
public class StreamDemo08 {

    public static void main(String[] args) {

        List<Author> authors = StreamDemoTest.getAuthors();

        /**
         * 打印所有书籍的名字，并且去重
         */

        /**
         * 📌 这段代码的逻辑是：
         * 遍历每一个不重复的 Author
         * 对每个作者的 Book 集合单独处理
         * 每个作者内部的 Book 流，获取书名、去重、打印
         * 📌 结果特征：
         * 按作者分批打印每位作者的书名（作者间可能有重复书名也会打印）
         * 每个作者自己的书名内部去重
         * 属于**“分组处理”**思想
         */
        authors.stream()
                .distinct() // 对 Author 去重（必须重写 equals 和 hashCode）
                .map(author -> author.getBooks().stream()) // 把每个作者的 book 列表映射成 Stream<Book>
                .forEach(new Consumer<Stream<Book>>() {
                    @Override
                    public void accept(Stream<Book> bookStream) {
                        bookStream.map(Book::getName) // 拿到书名
                                .distinct() // 去重书名（只是这个作者的书名中去重）
                                .forEach(System.out::println); // 打印书名
                    }
                });
        System.out.println("----------------------------------------------------");

        /**
         * 📌 这段代码的逻辑是：
         * 将所有作者的 Book 流展开合并成一个大流（不是作者内部分开处理）
         * 对 所有 Book 对象整体去重
         * 打印每本书的名字（全局唯一）
         * 📌 结果特征：
         * 所有书集中统一处理
         * 去除跨作者之间的重复书（完全相同的 Book）
         * 属于**“扁平处理 + 全局去重”**
         */
        authors.stream()
                .flatMap(new Function<Author, Stream<Book>>() {
                    @Override
                    public Stream<Book> apply(Author author) {
                        return author.getBooks().stream();
                    }
                })
                .distinct() // 对 Book 对象整体去重（要求 Book 类重写 equals/hashCode）
                .forEach(new Consumer<Book>() {
                    @Override
                    public void accept(Book book) {
                        System.out.println(book.getName());
                    }
                });
        System.out.println("----------------------------------------------------");

        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .forEach(book -> System.out.println(book.getName()));
        System.out.println("----------------------------------------------------");

        /**
         * 打印书籍分类并去重
         */
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .flatMap(book -> Arrays.stream(book.getCategory().split("，")))
                .distinct()
                .forEach(System.out::println);

        /**
         * map()：一对一 或 一对多映射，结果是嵌套结构；
         * flatMap()：将一对多展开成扁平结构，结果是扁平流。
         */
        /**
         * 比较点	         map()	                            flatMap()
         * 输入函数返回	    任意类型	                            必须是 Stream
         * 输出结果	        嵌套流结构（如 Stream<Stream<T>>）	    扁平流结构（Stream<T>）
         * 使用场景	        属性提取、简单转换	                    扁平化嵌套结构、展开列表/数组
         * 是否自动展开	    ❌ 否	                            ✅ 是
         */

    }

}
